#include "glwidget.h"

GLWidget::GLWidget(QWidget *parent) :
    QGLWidget(parent)
{
    v = NULL;
    volume = SDL_MIX_MAXVOLUME;
    dcThread = NULL;
    dmThread = NULL;
    reThread = NULL;
    aPlayer = NULL;
    setAutoBufferSwap(false);
}

GLWidget::~GLWidget() {
    stop();
    fsDisplay->close();
}

void GLWidget::setFSWindow(glFullScreenWindow *fsDisplay) {
    this->fsDisplay = fsDisplay;
}

void GLWidget::initializeGL() {

}

void GLWidget::paintGL() {
}

void GLWidget::play(QString vid_file_path) {
    if (!v)
        loadVideo(vid_file_path);

    if (v->state == PAUSED) {
        v->state = PLAY;
        return;
    }

    if (dmThread || dcThread || reThread || aPlayer) {
        return;
    }

    dmThread = new DemuxThread(NULL, v);
    dcThread = new DecodeThread(this, v);
    reThread = new RenderThread(this, fsDisplay, v);
    QThread::connect(reThread, SIGNAL(finishRender()), this, SLOT(stop()), Qt::QueuedConnection);
    QThread::connect(reThread, SIGNAL(setSlider(int)), this, SIGNAL(setSlider(int)), Qt::QueuedConnection);


    v->state = PLAY;
    dmThread->start();
    dcThread->start();
    reThread->start();
    aPlayer = new AudioPlayer(this, v);
    return;
}

void GLWidget::stop() {
    if (!v)
        return;

    v->state = STOPPED;

    dmThread->wait();
    dcThread->wait();
    reThread->wait();

    delete dmThread;
    delete dcThread;
    delete reThread;
    delete aPlayer;
    delete v;

    emit setSlider(0);

    dmThread = NULL;
    dcThread = NULL;
    reThread = NULL;
    aPlayer = NULL;
    v = NULL;
}
void GLWidget::pause() {
    if (!v)
        return;
    else if (v->state == STOPPED || v->state == STOPPING)
        return;
    else if (v->state == PLAY)
        v->state = PAUSED;
}
void GLWidget::fastForward() {
}
void GLWidget::fastBackward() {
}
void GLWidget::skipForward() {
}
void GLWidget::skipBackward() {
}

void GLWidget::loadVideo(QString vid_file_path) {
    if (!v)
        v = new Video();

    // Register all formats and codecs
    av_register_all();

    // Open video file
    QByteArray qba = vid_file_path.toLocal8Bit();
    const char* filename = qba.data();
    if(avformat_open_input(&v->formatCtx, filename, NULL, NULL) != 0) {
        clean();
        return; // Couldn't open file
    }

    // Retrieve stream information
    if(avformat_find_stream_info(v->formatCtx, NULL) < 0) {
        clean();
        return; // Couldn't find stream information
    }
    // Dump information about file onto standard error
    //av_dump_format(v->formatCtx, 0, filename, 0);

    // Find the first video stream
    v->videoIndex = -1;
    for (unsigned int i = 0; i < v->formatCtx->nb_streams; i++) {
        if (v->formatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
            v->videoIndex = (int)i;
            break;
        }
    }
    if (v->videoIndex == -1) {
        clean();
        return; // Didn't find a video stream
    }
    // Get a pointer to the codec context for the video stream
    v->vCodecCtx = v->formatCtx->streams[v->videoIndex]->codec;
    v->aspect_ratio = (double)v->vCodecCtx->height / (double)v->vCodecCtx->width;


    // Find the decoder for the video stream
    v->vCodec = avcodec_find_decoder(v->vCodecCtx->codec_id);
    if (v->vCodec == NULL) {
        fprintf(stderr, "Unsupported codec!\n");
        clean();
        return; // Codec not found
    }

    // Open codec
    if (avcodec_open2(v->vCodecCtx, v->vCodec, NULL) < 0) {
        clean();
        return; // Could not open codec
    }

    //find first audio stream
    v->audioIndex = -1;
    for (unsigned int i = 0; i < v->formatCtx->nb_streams; i++) {
        if(v->formatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
            v->audioIndex = (int)i;
            break;
        }
    }
    if(v->audioIndex == -1) {
        clean();
        return; // Didn't find an audio stream
    }
    //codecctx for audio stream
    v->aCodecCtx = v->formatCtx->streams[v->audioIndex]->codec;
    v->aCodec = avcodec_find_decoder(v->aCodecCtx->codec_id);
    if (v->aCodec == NULL) {
        fprintf(stderr, "Unsupported audio codec!\n");
        clean();
        return; // Codec not found
    }

    if (avcodec_open2(v->aCodecCtx, v->aCodec, NULL) < 0) {
        clean();
        return; // could not open audio codec
    }
}

void GLWidget::clean() {
    if (v) {
        stop();
    }
    else {
        if (dmThread) delete dmThread;
        if (dcThread) delete dcThread;
        if (reThread) delete reThread;
        if (aPlayer) delete aPlayer;
    }
}

void GLWidget::resizeGL(int w, int h) {
}
void GLWidget::resizeEvent(QResizeEvent *evt)
{
}
void GLWidget::paintEvent(QPaintEvent *) {}
void GLWidget::closeEvent(QCloseEvent *evt) {}
void GLWidget::mouseDoubleClickEvent(QMouseEvent *) {
    fsDisplay->show();
}


void GLWidget::setVolume(int volume) {
    this->volume = volume;
    if (v)
        v->volume = this->volume;
}
void GLWidget::seek(int millentage) {
    if (v)
        if (!v->seekFlag) {
            v->seekFlag = true;
            v->seekPos = (double)millentage/1000;
        }
    std::cout << "seeeek: " << millentage << std::endl;
}

